/**
 * Copyright (c) 2025 myons Inc. All rights reserved.
 */
package cn.zmwh.manage.admin.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.zmwh.common.core.constants.Constants;
import cn.zmwh.common.security.annotation.PreRole;
import cn.zmwh.manage.admin.modules.upms.mapper.SysMenuMapper;
import cn.zmwh.manage.admin.modules.upms.mapper.SysRoleMapper;
import cn.zmwh.manage.admin.modules.upms.mapper.SysRoleMenuMapper;
import cn.zmwh.manage.admin.modules.upms.pojo.entity.SysMenu;
import cn.zmwh.manage.admin.modules.upms.pojo.entity.SysRole;
import cn.zmwh.manage.admin.modules.upms.pojo.entity.SysRoleMenu;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @describe: 加载权限 、
 * @author: dmzmwh 、
 * @time: 2025-03-29 10:35 、
 */
@Slf4j
@Configuration
public class InitMenuConfig implements ApplicationRunner {

    @Autowired
    private RequestMappingHandlerMapping rmhm;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public void run(ApplicationArguments args) {
        try {
            Date date = new Date();
            log.info("初始化角色权限-----" + DateUtil.format(date, "yyyy-MM-dd HH:mm:ss"));
            Set<SysMenu> byAll = sysMenuMapper.findByAll(Constants.HT_URL);
            List<SysRole> sysRoles = sysRoleMapper.selectList(null);
            Map<RequestMappingInfo, HandlerMethod> handlerMethods = rmhm.getHandlerMethods();
            Set<Map.Entry<RequestMappingInfo, HandlerMethod>> entries = handlerMethods.entrySet();
            for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : entries) {
                HandlerMethod handlerMethod = entry.getValue();
                PreRole preRole = handlerMethod.getMethodAnnotation(PreRole.class);
                if (preRole == null) {
                    continue;
                }
                RequestMappingInfo key = entry.getKey();
                PatternsRequestCondition patternsCondition = key.getPatternsCondition();
                Set<String> patterns = patternsCondition.getPatterns();
                String name = preRole.name();
                Set<Long> roleIds = loadRole(preRole, sysRoles);

                for (String pattern : patterns) {
                    SysMenu menu = new SysMenu();
                    menu.setPath(pattern);
                    menu.setName(name);
                    menu.setMenuType("ht_url");
                    if (byAll.contains(menu)) {
                        //todo 可以在此处检测菜单是否变更过角色处理历史数据，太麻烦手动删除吧
                        byAll.remove(menu);
                        continue;
                    }
                    menu.setPid(0L);
                    menu.setCreateTime(date);
                    menu.setUpdateTime(date);
                    sysMenuMapper.insert(menu);
                    if (CollUtil.isEmpty(roleIds)) {
                        continue;
                    }
                    Long id = menu.getId();
                    List<SysRoleMenu> list = new ArrayList<>();
                    for (Long roleId : roleIds) {
                        SysRoleMenu roleMenu = new SysRoleMenu();
                        roleMenu.setRoleId(roleId);
                        roleMenu.setMenuId(id);
                        roleMenu.setCreateTime(new Date());
                        list.add(roleMenu);
                    }
                    sysRoleMenuMapper.insert(list);
                }
            }
            if (CollUtil.isNotEmpty(byAll)) {
                Set<Long> ids = byAll.stream().map(SysMenu::getId).collect(Collectors.toSet());
                sysMenuMapper.deleteByIds(ids);
            }
        } catch (Exception e) {
            log.error("需要重视，加载权限失败加载权限失败加载权限失败加载权限失败加载权限失败加载权限失" +
                    "败加载权限失败加载权限失败加载权限失败加载权限失败加载权限失败加载权限失败" +
                    "加载权限失败加载权限失败加载权限失败加载权限失败加载权限失败加载权限失败", e);
        }
    }

    /**
     * 加载用户角色
     *
     * @param preRole
     * @param sysRoles
     */
    private Set<Long> loadRole(PreRole preRole, List<SysRole> sysRoles) {
        Set<String> roles = new HashSet<>();
        String role = preRole.role();
        if (StrUtil.isNotBlank(role)) {
            roles.add(role);
        } else {
            String[] rolesStr = preRole.roles();
            if (rolesStr != null && rolesStr.length > 0) {
                for (String s : rolesStr) {
                    roles.add(s);
                }
            }
        }
        if (CollUtil.isEmpty(roles)) {
            return null;
        }
        Set<Long> roleIds = new HashSet<>();
        for (SysRole sysRole : sysRoles) {
            String role1 = sysRole.getRole();
            if (roles.contains(role1)) {
                roleIds.add(sysRole.getId());
            }
        }
        Set<String> collect = sysRoles.stream().map(SysRole::getRole).collect(Collectors.toSet());
        roles.removeAll(collect);
        if (CollUtil.isEmpty(roles)) {
            return roleIds;
        }
        for (String roleName : roles) {
            SysRole sysRole = new SysRole();
            sysRole.setRole(roleName);
            sysRole.setName(roleName);
            sysRole.setCreateTime(new Date());
            sysRole.setUpdateTime(new Date());
            sysRoleMapper.insert(sysRole);
            log.info("新增角色" + sysRole.getRole());
            roleIds.add(sysRole.getId());
            sysRoles.add(sysRole);//防止多次增加相同角色
        }
        return roleIds;
    }


}
